using System.IO;

namespace Cirrostrata.Abstractions
{
    internal static class StreamExtensions
    {
        private const int DefaultBufferSize = 65536;

        #region Public Methods
        // ------------------------------------------------------------------------------------

        /// <summary>
        /// Copy this stream to another stream. Use default buffer size of 64k
        /// </summary>
        /// <param name="i">The source stream</param>
        /// <param name="o">The destination stream</param>
        /// <returns>Number of bytes copied</returns>
        public static long CopyTo(this Stream i, Stream o)
        {
            return CopyTo(i, o, DefaultBufferSize);
        }

        /// <summary>
        /// Copy this stream to another stream. 
        /// </summary>
        /// <param name="i">The source stream</param>
        /// <param name="o">The destination stream</param>
        /// <param name="bufSize">Size of streaming buffer</param>
        /// <returns>Number of bytes copied</returns>
        public static long CopyTo(this Stream i, Stream o, int bufSize)
        {
            long copied = 0;
            int read;

            var buf = new byte[bufSize];

            do
            {
                read = i.Read(buf, 0, bufSize);
                if (read > 0)
                {
                    o.Write(buf, 0, read);
                    copied += read;
                }
            } while (read > 0);

            return copied;
        }

        public static bool CompareTo(this Stream s1, Stream s2)
        {
            return s1.CompareTo(s2, DefaultBufferSize);
        }

        public static bool CompareTo(this Stream s1, Stream s2, int bufSize)
        {
            var br1 = new BinaryReader(s1);
            var br2 = new BinaryReader(s2);

            int read;

            do
            {
                var buf1 = br1.ReadBytes(bufSize);
                var buf2 = br2.ReadBytes(bufSize);

                if (buf1.Length != buf2.Length)
                    return false;

                read = buf1.Length;

                for (int i = 0; i < read; i++)
                {
                    if (buf1[i] != buf2[i])
                        return false;
                }

            } while (read == bufSize);

            return true;
        }

        #endregion
    }
}